package com.audaque.encoding.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.audaque.encoding.dto.AnalysisInfo;
import com.audaque.encoding.dto.TableFieldInfo;
import com.audaque.encoding.dto.ValueInfo;
import com.audaque.encoding.mapper.PostgreSQLCommonMapper;
import com.audaque.encoding.service.HandleCallbackService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author mayong
 * @since 2024/7/8
 */
@Slf4j
@Data
@Component
@Scope("prototype")
@EqualsAndHashCode(callSuper = true)
public class PostgreSQLListener extends AnalysisEventListener<Map<Integer, String>> {


    private AnalysisInfo analysisInfo;
    private PostgreSQLCommonMapper postgreSQLCommonMapper;
    private HandleCallbackService handleCallbackService;

    private int sum = 0;

    private static final int BATCH_COUNT = 500;

    // 新增sql准备的数据
    List<List<String>> dataLists = new LinkedList<>(); // 存放每一行的数据
    List<String> headerList = new LinkedList<>();  // 存放每一列的header名
    List<Integer> indexList = new LinkedList<>(); // 存放要素名称和赋码结果字段的索引
    // 更新sql准备的数据
    private final List<ValueInfo> updateData = new ArrayList<>(); // 存放更新语句的条件

    private int index1 = -1; // 记录赋码结果字段的索引
    private int index2 = -1; // 记录要素名称字段的索引

    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        // key存放列索引，value存放列名对应的value
        List<String> dataList = new LinkedList<>();
        ValueInfo valueInfo = new ValueInfo();
        // 将dataMap中的value存放到dataList中
        for (Map.Entry<Integer, String> entry : data.entrySet()) {
            if(indexList.contains(entry.getKey())){
                dataList.add(entry.getValue());
            }
            if(index1 == entry.getKey()){
                valueInfo.setResultValue(entry.getValue());
            }
            if(index2 == entry.getKey()){
                valueInfo.setBizValue(entry.getValue());
            }
        }
        updateData.add(valueInfo);
        dataLists.add(dataList);
        // 判断缓存是否已满，若已满则进行插入操作
        if (dataLists.size() >= BATCH_COUNT) {
            batch();
        }

    }

    // 执行批量化新增到目标表的操作
    private void insertBatch() {
        log.info("执行数据新增");
        if(StringUtils.equals(analysisInfo.getDatabase(),"dzd")){
            //现场说不要新增了
//            postgreSQLCommonMapper.insertData2(analysisInfo.getTargetTableName(),analysisInfo.getTargetSchema(),headerList,dataLists);

        }
        if(StringUtils.equals(analysisInfo.getDatabase(),"adq_")){
            postgreSQLCommonMapper.insertData(analysisInfo.getTargetTableName(),analysisInfo.getTargetSchema(),headerList,dataLists);
        }
    }

    private void updateBatch() {
        log.info("执行数据更新");
        postgreSQLCommonMapper.updateDate(analysisInfo,updateData);
    }

    private void batch() {
        insertBatch();
        dataLists.clear();
        updateBatch();
        updateData.clear();
    }


    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 1. insert into target (col1, col2, col3) values (?,?,?)
        // 2. update source set tysbdm ='统一识别代码' where ysmc = '要素名称'
        // 组装成insert语句的时候就分别遍历headerMap和dataMap，然后组装成insert语句
        batch();
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        headerList.clear();
        log.info("获取表头信息");
        // 要数名称 和 赋码结果字段
        List<TableFieldInfo> fields = analysisInfo.getFields();
        // 将fields 转换成 以comment为key的map
        Map<String, String> fileNameMap = fields.stream().collect(Collectors.toMap(TableFieldInfo::getComment, TableFieldInfo::getFieldName));
        // 遍历headMap，将其中的值存入headerList中
        for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
            String header = entry.getValue();
            if (fileNameMap.containsKey(header)) {
                headerList.add(fileNameMap.get(header));
                indexList.add(entry.getKey());
            }
            if(StringUtils.equals(entry.getValue(),analysisInfo.getBizName())){
                index2 = entry.getKey();
            }
            if(StringUtils.equals(entry.getValue(),analysisInfo.getResultName())){
                index1 = entry.getKey();
            }

        }
    }
}
